package org.flexthinker.binding.value.support
{
    import mx.collections.ArrayCollection;
    import mx.collections.IList;

    import mx.collections.ListCollectionView;

    import org.flexthinker.binding.value.ValueChangeDetector;

    /**
     * Compares 2 lists by looking at list length and if length differs, it
     * also looks at the elements
     *
     * @see EqualsValueChangeDetector
     */
    public class ListValueChangeDetector implements ValueChangeDetector
    {
        private var equalsChangeDetector:EqualsValueChangeDetector = new EqualsValueChangeDetector();

        public function ListValueChangeDetector():void
        {
        }

        public function hasValueChanged(oldValue:Object, newValue:Object):Boolean
        {
            if ( oldValue is IList && newValue is IList )
            {
                return !sameList(IList(oldValue), IList(newValue) );
            }

            return equalsChangeDetector.hasValueChanged( oldValue, newValue);
        }

        private function sameLength( oldValue:IList, newValue:IList ):Boolean
        {
            return oldValue.length == newValue.length;
        }

        private function sameList( oldValue:IList, newValue:IList ):Boolean
        {
            if ( !sameLength(oldValue, newValue))
            {
                return false;
            }

            var n:int = oldValue.length;
            var usedIndexes:Array = [];
            var index:int;
            for ( var i:int = 0; i < n; i++)
            {
                index = newValue.getItemIndex( oldValue.getItemAt(i) );
                if ( index  < 0 || usedIndexes.indexOf(index) >= 0 )
                {
                    return false;
                }
                usedIndexes.push( index );
            }

            return true;
        }

    }
}
